home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / graphicgems4.lha / GemsIV / arcball / BallMath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  2.4 KB  |  87 lines

  1. /**** BallMath.c - Essential routines for ArcBall.  ****/
  2. #include <math.h>
  3. #include "BallMath.h"
  4. #include "BallAux.h"
  5.  
  6. /* Convert window coordinates to sphere coordinates. */
  7. HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius)
  8. {
  9.     HVect ballMouse;
  10.     register double mag;
  11.     ballMouse.x = (mouse.x - ballCenter.x) / ballRadius;
  12.     ballMouse.y = (mouse.y - ballCenter.y) / ballRadius;
  13.     mag = ballMouse.x*ballMouse.x + ballMouse.y*ballMouse.y;
  14.     if (mag > 1.0) {
  15.     register double scale = 1.0/sqrt(mag);
  16.     ballMouse.x *= scale; ballMouse.y *= scale;
  17.     ballMouse.z = 0.0;
  18.     } else {
  19.     ballMouse.z = sqrt(1 - mag);
  20.     }
  21.     ballMouse.w = 0.0;
  22.     return (ballMouse);
  23. }
  24.  
  25. /* Construct a unit quaternion from two points on unit sphere */
  26. Quat Qt_FromBallPoints(HVect from, HVect to)
  27. {
  28.     Quat qu;
  29.     qu.x = from.y*to.z - from.z*to.y;
  30.     qu.y = from.z*to.x - from.x*to.z;
  31.     qu.z = from.x*to.y - from.y*to.x;
  32.     qu.w = from.x*to.x + from.y*to.y + from.z*to.z;
  33.     return (qu);
  34. }
  35.  
  36. /* Convert a unit quaternion to two points on unit sphere */
  37. void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo)
  38. {
  39.     double s;
  40.     s = sqrt(q.x*q.x + q.y*q.y);
  41.     if (s == 0.0) {
  42.     *arcFrom = V3_(0.0, 1.0, 0.0);
  43.     } else {
  44.     *arcFrom = V3_(-q.y/s, q.x/s, 0.0);
  45.     }
  46.     arcTo->x = q.w*arcFrom->x - q.z*arcFrom->y;
  47.     arcTo->y = q.w*arcFrom->y + q.z*arcFrom->x;
  48.     arcTo->z = q.x*arcFrom->y - q.y*arcFrom->x;
  49.     if (q.w < 0.0) *arcFrom = V3_(-arcFrom->x, -arcFrom->y, 0.0);
  50. }
  51.  
  52. /* Force sphere point to be perpendicular to axis. */
  53. HVect ConstrainToAxis(HVect loose, HVect axis)
  54. {
  55.     HVect onPlane;
  56.     register float norm;
  57.     onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose)));
  58.     norm = V3_Norm(onPlane);
  59.     if (norm > 0.0) {
  60.     if (onPlane.z < 0.0) onPlane = V3_Negate(onPlane);
  61.     return ( V3_Scale(onPlane, 1/sqrt(norm)) );
  62.     } /* else drop through */
  63.     if (axis.z == 1) {
  64.     onPlane = V3_(1.0, 0.0, 0.0);
  65.     } else {
  66.     onPlane = V3_Unit(V3_(-axis.y, axis.x, 0.0));
  67.     }
  68.     return (onPlane);
  69. }
  70.  
  71. /* Find the index of nearest arc of axis set. */
  72. int NearestConstraintAxis(HVect loose, HVect *axes, int nAxes)
  73. {
  74.     HVect onPlane;
  75.     register float max, dot;
  76.     register int i, nearest;
  77.     max = -1; nearest = 0;
  78.     for (i=0; i<nAxes; i++) {
  79.     onPlane = ConstrainToAxis(loose, axes[i]);
  80.     dot = V3_Dot(onPlane, loose);
  81.     if (dot>max) {
  82.         max = dot; nearest = i;
  83.     }
  84.     }
  85.     return (nearest);
  86. }
  87.